package concurrent;

import java.util.concurrent.*;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.IntStream;

/**
 * 可重入锁：可重入锁是指同一个线程可以多次获得同一把锁；ReentrantLock和关键字Synchronized都是可重入锁
 * 可中断锁：可中断锁时只线程在获取锁的过程中，是否可以相应线程中断操作。synchronized是不可中断的，ReentrantLock是可中断的
 * 公平锁和非公平锁：公平锁是指多个线程尝试获取同一把锁的时候，获取锁的顺序按照线程到达的先后顺序获取，而不是随机插队的方式获取。synchronized是非公平锁，而ReentrantLock是两种都可以实现，不过默认是非公平锁
 *
 * @author jack.wu
 * @since 2019/8/31 15:13
 */
public class ReetranLockTest {

    private static ReentrantLock lock = new ReentrantLock();

    private static int i = 1;

    private static Runnable runnable = () -> IntStream.range(0, 100).forEach(j -> {
        lock.lock();
        try {
            i++;
        } finally {
            lock.unlock();
        }
    });

    private static Runnable runnable1 = () -> {
        try {
            lock.lockInterruptibly();
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            // 处理中断异常
            e.printStackTrace();
        } finally {
            String threadName = Thread.currentThread().getName();
            if ("Thread-1".equals(threadName)) {
                lock.unlock();
            }
            System.out.println(threadName + "停止");
        }
    };

    private static Runnable runnable2 = () -> {
        try {
            try {
                if (lock.tryLock(3, TimeUnit.SECONDS)) {
                    Thread.sleep(5000);
                } else {
                    System.out.println(Thread.currentThread().getName() + "获取锁失败");
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } finally {
            if (lock.isHeldByCurrentThread()) {
                // 还保持着锁的状态
                System.out.println(Thread.currentThread().getName() + "释放锁了");
                lock.unlock();
            }

        }
    };

    public static void main(String[] args) throws InterruptedException {
//        Thread t1 = new Thread(runnable);
//        Thread t2 = new Thread(runnable);
//        t1.start();
//        t2.start();
//        // 利用join，等thread1 和thread2结束后，main线程才继续运行，并打印i
//        t1.join();
//        t2.join();
//        System.out.println(i);

//        Thread thread1 = new Thread(runnable1, "Thread-1");
//        Thread thread2 = new Thread(runnable1, "Thread-2");
//        thread1.start();
//        Thread.sleep(1000);
//        thread2.start();
//        thread2.interrupt();

        Thread thread1 = new Thread(runnable2, "Thread-1");
        Thread thread2 = new Thread(runnable2, "Thread-2");
        thread1.start();
        thread2.start();
    }
}

